#pragma once 
#include <bits/stdc++.h>

/*****************************************************************************
 *! @brief C++提供了原子类型std::atomic<T>, 可以使用任意类型作为模板参数， 内置了整型的
 *!        原子变量, 使用原子变量就不用互斥量保护该变量了，使用起来更加简洁.     
 *
 *         
 *           
 * 
 *  
 ****************************************************************************/

//!  1. 基于互斥量的多线程保护
struct Counter {
	int value = 0;
	std::mutex mutex;

	void increment() {
		std::lock_guard<std::mutex> lock(mutex);
		++value;
		std::cout << value << std::endl;
	}

	void decrement() {
		std::lock_guard<std::mutex> lock(mutex);
		--value;
		std::cout << value << std::endl;
	}

	int get() {
		return value;
	}
};

//! 2. 基于原子变量的互斥保护
struct CounterAtomic {
	std::atomic<int> value{0};

	void increment() {
		++value;
	}

    /**
     *! @brief atomic<int> 其它操作
     *
     *! 1. 加法和减法
     *    value += 5;
     *    value -= 5;
     * 
     *! 2. 加法和减法的取值操作  fetch_add 和 fetch_sub
     *    int old_value = value.fetch_add(2);       // 原子地将 value 增加 2，并返回增加前的值
     *    old_value = value.fetch_sub(1);           // 原子地将 value 减少 1，并返回减少前的值
     *   
     *! 3. 按位操作: fetch_or、fetch_and、fetch_xor
     *    old_value = value.fetch_or(0b0101);       // 原子地进行按位或操作，并返回操作前的值
     *    old_value = value.fetch_and(0b1110);      // 原子地进行按位与操作，并返回操作前的值
     *    old_value = value.fetch_xor(0b1010);      // 原子地进行按位异或操作，并返回操作前的值
     *
     * 
     *!  4. 比较和交换操作: compare_exchange_weak 和 compare_exchange_strong
     *     int expected   = 10;
     *     bool exchanged = value.compare_exchange_strong(expected, 20);
     *     * 如果 value 等于 expected，则将 value 设置为 20，并返回 true
     *     * 否则，将 expected 设置为 value 的当前值，并返回 false
     * 
     *     * compare_exchange_weak: 即使当前值和期望值一致，它也可能返回 false 并什么都不做。这可能
     *     *                        是因为其他线程同时修改了该值，也可能是因为硬件平台的实现细节。
     * 
     * 
     *!  5. 加载和存储: load 和 store
     *     int current = value.load();             // 原子地加载 value 的当前值
     *     value.store(15);                        // 原子地将 value 的值设置为 15
     *
     * 
     *!  6. 其它
     *     old_value = value.exchange(30);         // 原子地将 value 设置为 30，并返回之前的值
     * 
     */

	void decrement() {
		--value;
	}

	int get() {
		return value;
	}
};


//! 3. std::atomic支持自定义类型
/**
 * @brief  在 C++ 中，std::atomic<T> 支持自定义类型 T 可以在多线程环境中安全地对这些类型的对象进行操作。这意味着你
 *         可以创建一个能够保证线程安全性的原子自定义类型，对于并发编程而言非常重要。不过，要注意的是，T 必须满足 
 *         TriviallyCopyable 的要求，即它们可以通过简单的内存复制安全地复制和移动。
 * 
 * 
 * 使用 std::atomic<T> 支持自定义类型的好处
 *        1). 线程安全：在多线程程序中，原子操作保证了对共享数据的安全访问，防止了数据竞争和其他并发相关的问题。
 *        2). 无锁编程：使用 std::atomic 可以避免显式的锁定和解锁操作，从而简化代码并提高性能。
 *        3). 同步和顺序保证：原子操作还提供了内存顺序和可见性保证，这对于正确的并发编程至关重要。
 */
//! TODO: 完成这部分知识点



int std_atomic();